using System;
using System.Collections.Generic;
using System.Data;
using System.Reflection;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace Web.Ajax.Controls
{
    [ToolboxData("<{0}:Questions runat=\"server\"></{0}:Questions>")]
    [ParseChildren(false)]
    public class Questions : AjaxControl
    {
        public Questions()
        {
            Height = new System.Web.UI.WebControls.Unit("500px");
            Width = new System.Web.UI.WebControls.Unit("100%");
        }

        protected override void OnInit(EventArgs e)
        {
            Ajax.RegisterAjaxMethods(this);
            base.OnInit(e);
            if (PopupTitle != null)
                if (PopupTitle.TitleRight != null)
                    PopupTitle.TitleRight.DisplayClose = false;
            Web.Ajax.Page p = Page as Web.Ajax.Page;
            if (p != null)
            {
				p.RegisterJavascriptFile(Resources.Javascript.AjaxControl);
				p.RegisterStyleSheet(Resources.StyleSheets.Questions);
                p.RegisterJavascriptFile(Resources.Javascript.Questions);
                p.RegisterJavascriptFile(Resources.Javascript.Validator);
				Calendar.RegisterResources(p);
            }
        }

        /// <summary>
        /// The signature for the static method used to return the Tree data.
        /// </summary>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public delegate QuestionData[] GetDataMethod(QuestionInfo QuestionInfo);
        public GetDataMethod DataMethod;
        
        

        private Unit optionWidth;
        public Unit OptionWidth
        {
            get
            { return optionWidth; }
            set
            { optionWidth = value; }
        }

		public bool FixedHeight;

        protected override void Render(HtmlTextWriter writer)
        {
            if (DataMethod == null)
                throw new Exception("DataMethod was not set on Questions: " + JavascriptId + ". A DataMethod must be provided for the Questions to work.");
            if (!Visible)
                return;
            StringBuilder html = new StringBuilder();
            html.Append("<div class=\"QuestionPanel\" id=\"" + JavascriptId + "\" style=\"" +(FixedHeight?("height: "+Height.ToString()+";"):"")+"width: "+Width.ToString()+";"+GetPositionString()+"\">");
            html.Append("<div id=\"" + JavascriptId + "_Content\" style=\"height:100%;\"></div></div>");
            writer.Write(html.ToString());
            writer.WriteLine("<script type=\"text/javascript\">");
            writer.WriteLine("var " + JavascriptId + " = new Questions('" + JavascriptId + "','" + DataMethod.Method.DeclaringType.AssemblyQualifiedName + "','" + DataMethod.Method.Name + "');");
            RenderProperty(writer, "NoData", NoData);
            if(OptionWidth!=null)
                RenderProperty(writer, "OptionWidth", OptionWidth.ToString());
            RenderJavascriptId(writer);
            RenderParameters(writer);
            writer.WriteLine("</script>");
        }

        [Ajax]
        public static QuestionResponse GetData(QuestionRequest request)
        {
            QuestionResponse response= new QuestionResponse();
            try
            {
                Type Type = System.Type.GetType(request.DataMethodType);
                if (Type == null)
                    throw new Exception("AjaxQuestions: Invalid Type.");
                MethodInfo Method = Type.GetMethod(request.DataMethodName);
                if (request.QuestionInfo.Parameters == null)
                    request.QuestionInfo.Parameters = new Parameter[0];
                object o = null;
                o = Method.Invoke(null, new object[] { request.QuestionInfo });
                if (o == null || !(o is QuestionData[]))
                    throw new Exception("AjaxQuestions: Data Method did not return a QuestionData[].");
                response.Data = (QuestionData[])o;
                response.OnComplete = request.QuestionInfo.OnComplete;
            }
            catch (Exception e)
            {
                if (e.InnerException != null)
                    response.Message = e.InnerException.Message;
                else
                    response.Message = e.Message;
            }
            return response;
        }
    }


    public class QuestionInfo : ControlInfo
    {
        public QuestionData[] QuestionData;

        public QuestionData GetQuestion(string Id)
        {
            if (QuestionData == null || string.IsNullOrEmpty(Id))
                return null;
            for (int i = 0; i < QuestionData.Length; i++)
                if (QuestionData[i].Id == Id)
                    return QuestionData[i];
            return null;
        }

        public string GetAnswer(string Id)
        {
            QuestionData q = GetQuestion(Id);
            if (q != null)
                return q.Answer;
            return null;
        }

        public int? GetIntAnswer(string Id)
        {
            try
            {
                return int.Parse(GetAnswer(Id));
            }
            catch
            {
                return null;
            }
        }

        public bool? GetBoolAnswer(string Id)
        {
            try
            {
                return bool.Parse(GetAnswer(Id));
            }
            catch
            {
                return null;
            }
        }

        public void HideAllQuestions()
        {
            if (QuestionData==null)
                return;
            for (int i = 0; i < QuestionData.Length; i++)
                QuestionData[i].Visible = false;
        }

        public void ShowQuestion(string Id)
        {
            QuestionData q = GetQuestion(Id);
            if (q != null)
                q.Visible=true;
        }

        public void SetAnswer(string Id, string Answer)
        {
            QuestionData q = GetQuestion(Id);
            if (q != null)
                q.Answer=Answer;
        }
    }

    public enum QuestionType
    {
        Text,
        //Numeric,
        Bool,
        Options,
		TextArea,
		DateTime
    }

    public class QuestionData
    {
        public string Id;
        public string Text;
        public string Answer;
        public int Min;
        public int Max;
        public QuestionType Type;
        public string[] Options;
        public bool Required;
        public string ErrorMessage;
        public string RegEx;
        public string ValidationFunction;
        public bool Visible=true;
        public bool Enabled = true;
		public bool Readonly;
        public string[] DependentQuestionIds;
        public string[] EnableDependentsAnswers;
    }

    public class QuestionRequest : AjaxControlRequest
    {
        public QuestionInfo QuestionInfo;
    }

    public class QuestionResponse : AjaxControlResponse
    {
        public QuestionData[] Data;
    }
}
